package service

import (
	"census/context"
	"errors"
	"fmt"
	"os"
)

type Service interface {
	SID() string //标识
	Run() error
	Reload() error
	Shutdown() error
	Send(*context.AppRequest) error
}

var (
	fileFDs   []*os.File
	container map[string]Service
	done      chan struct{}
)

var (
	errServiceExist      = errors.New("service has exist")
	errServiceNotExist   = errors.New("service not exist")
	errServiceAtLeastOne = errors.New("service at least one")
)

func init() {
	fileFDs = make([]*os.File, 63)
	container = make(map[string]Service)
	done = make(chan struct{})
}

func Add(i Service) (err error) {
	if _, ok := container[i.SID()]; ok {
		err = errServiceExist
	}
	container[i.SID()] = i
	return
}

func Delete(i Service) (err error) {
	if _, ok := container[i.SID()]; !ok {
		err = errServiceNotExist
	}
	delete(container, i.SID())
	return
}

func GetServiceChan() <-chan struct{} {
	return done
}

func CloseServiceChan() {
	close(done)
}

func GetAllFileFDs() []*os.File {
	return fileFDs
}

func addFileFD(key int, f *os.File) {
	fileFDs[key] = f
}

func StartAll() (err error) {
	if len(container) == 0 {
		err = errServiceAtLeastOne
	}
	for _, o := range container {
		go o.Run()
	}
	return
}

func StopAll() {
	//关闭信道
	CloseServiceChan()
	for _, o := range container {
		fmt.Printf("[execute]: service %v shutdown.\n", o.SID())
		o.Shutdown()
		fmt.Printf("[end]: service %v shutdown success.\n", o.SID())
	}
}

func ReloadAll() {
	for _, o := range container {
		fmt.Printf("[execute]: service %v reload.\n", o.SID())
		o.Reload()
		fmt.Printf("[end]: service %v reload success.\n", o.SID())
	}
}
